/*
 * Licensed to the Tai Ping Jin Ke
 *
 * Copyright (c) 2022 .
 * All rights reserved.
 * 项目名称：呼叫中心-请求处理层-工作台
 * 版权说明：本软件属太平金融科技服务(上海)有限公司所有，在未获得太平金融科技服务(上海)有限公司正式授权情况下，任何企业和个人，不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 */
package com.taiping.cc.platform.webapi.handler;

import cn.hutool.core.io.IoUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.taiping.cc.platform.service.PlatformService;
import com.taiping.cc.platform.webapi.vo.ArticleBO;
import com.taiping.cc.platform.webapi.vo.ArticleVO;
import com.taipingframework.boot.web.response.result.ApiResult;
import com.taipingframework.boot.web.response.status.ApiStatusEnum;
import com.taipingframework.boot.web.websocket.WebSocketService;
import com.taipingframework.json.JacksonHelper;
import com.taipingframework.utility.exception.ApplicationException;
import com.taipingframework.utility.exception.SystemInterrupterException;
import com.taipingframework.utility.extend.ServletHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import java.util.TreeMap;

@Slf4j
@Component
@RequiredArgsConstructor
public class IndexHandler {

    private final WebSocketService webSocketService;
    private final PlatformService platformService;

    /**
     * 查询工作台数据
     */
    public ApiResult<TreeMap<String, String>> queryForActionDataList() throws ApplicationException {
        try {
            return platformService.queryForActionDataList();
        } catch (Exception e) {
            throw new ApplicationException(e);
        }
    }

    /**
     * 分布式全局唯一ID生成
     */
    public ApiResult<ArrayList<String>> listUnid() throws ApplicationException {
        try {
            return platformService.unidList();
        } catch (Exception e) {
            throw new ApplicationException(e);
        }
    }

    /**
     * 分布式锁解决方案 - redis
     */
    public ApiResult<Boolean> redisLock() throws ApplicationException {
        try {
            return platformService.redisLock();
        } catch (Exception e) {
            throw new ApplicationException(e);
        }
    }

    /**
     * 分布式锁解决方案 - zookeeper
     */
    public ApiResult<Boolean> zkLock() throws ApplicationException {
        try {
            return platformService.zkLock();
        } catch (Exception e) {
            throw new ApplicationException(e);
        }
    }

    /**
     * 文件上传
     */
    public ApiResult<HashMap<String, String>> uploadAttachment(String test, MultipartFile file) throws ApplicationException {
        try {
            ApiResult<HashMap<String, String>> hashMapApiResult = platformService.uploadAttachment(file);
            hashMapApiResult.getResult().put("test", test);
            return hashMapApiResult;
        } catch (Exception e) {
            throw new ApplicationException(e);
        }
    }

    /**
     * 文件下载
     */
    public void downloadAttachment(String objectName) throws ApplicationException {
        try {
            // feign 接口获取文件流
            ResponseEntity<Resource> fileResponse = platformService.downloadAttachment(objectName);

            // 设置响应头
            List<String> contentDispositionList = new ArrayList<>();
            contentDispositionList.add("attachment; filename=" + java.net.URLEncoder.encode(objectName, StandardCharsets.UTF_8.name()));
            contentDispositionList = Optional.ofNullable(fileResponse.getHeaders().get(HttpHeaders.CONTENT_DISPOSITION))
                    .orElse(contentDispositionList);

            HttpServletResponse response = ServletHelper.getResponse();
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, contentDispositionList.get(0));
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);

            // 从 Feign 响应中获取文件输入流，并写入到 HttpServletResponse 输出流中
            InputStream inputStream = Optional.ofNullable(fileResponse.getBody())
                    .orElseThrow(() -> new SystemInterrupterException(ApiStatusEnum.ERR_B0321))
                    .getInputStream();
            OutputStream output = response.getOutputStream();
            IoUtil.copy(inputStream, output);

            // 将流刷新给到浏览器
            response.flushBuffer();
        } catch (Exception e) {
            throw new ApplicationException(e);
        }
    }

    /**
     * 后端通过WebSocket向前端推送消息
     */
    public void sendMessage(String channelKey, String message) throws ApplicationException {
        try {
            webSocketService.sendToClient(channelKey, message);
        } catch (Exception e) {
            throw new ApplicationException(e);
        }
    }

    /**
     * 获取文章列表
     */
//CHECKSTYLE:OFF
    public ApiResult<ArticleVO> getTableList(String requestBody) throws ApplicationException {
        try {
            log.debug("前端数据：{}", requestBody);
            // 临时读取classpath下的mock数据
            StringBuilder tableListBuilder = new StringBuilder();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new ClassPathResource("table-list.json").getInputStream()));
            String data;
            while ((data = bufferedReader.readLine()) != null) {
                tableListBuilder.append(data);
            }
            bufferedReader.close();
            // 获取文章列表
            List<ArticleBO> articleBOList = JacksonHelper.from(tableListBuilder.toString(), new TypeReference<List<ArticleBO>>() {
            });
            // 封装前端页面数据对象
            ArticleVO articleVO = new ArticleVO();
            articleVO.setSize(100L);
            articleVO.setArticleList(articleBOList);

            return ApiResult.<ArticleVO>build()
                    .setStatus(ApiStatusEnum.SUCCESS)
                    .setResult(articleVO);
        } catch (Exception e) {
            throw new ApplicationException(e);
        }
    }
//CHECKSTYLE:ON
}
